package piwan.editor;

import piwan.*;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Scanner;

import javax.media.opengl.GL;

public class EditPoly {	
	public EditPoly() {
		verts = new ArrayList<EditVertex>();
	}
	
	public ArrayList<EditVertex>	getVertices() { return verts; }
	//public ArrayList<Resource>		getResources() { return res; }
	public int getVertexCount() { return verts.size(); }
	
	public void addToVertices() {
		for(EditVertex v: verts)
			v.addPoly(this);
	}
	
	public void removeFromVertices() {
		for(EditVertex v: verts)
			v.removePoly(this);
	}
	
	public void addVertex( EditVertex vert ) {
		verts.add(vert);
		vertsum.add(vert.getPosition());
		updateCenter();
		
	}
	
	public void removeVertex( EditVertex vert ) {
		verts.remove(vert);
		vertsum.sub(vert.getPosition());
		updateCenter();
	}
	
	public void close() { closed = true; }
	
	public boolean isPointInside( Vector2 v ) {
		int i, ps = verts.size(), j =ps-1;
		boolean oddNodes=false;
		if( ps < 3 ) return false;
		for(i=0;i<ps;++i) {
			 Vector2 vi = verts.get(i).getPosition();
			 Vector2 vj = verts.get(j).getPosition();
			 if(vi.y<v.y && vj.y >= v.y || vj.y<v.y && vi.y>=v.y) {
				 if( vi.x + (v.y-vi.y)/(vj.y-vi.y) * (vj.x-vi.x) < v.x ) {
					 oddNodes = !oddNodes;
				 }
			 }
			 j=i;
		}
		
		return oddNodes;
	}
	
	public void renderPoints(GL gl) {
		for(EditVertex v: verts)
			v.render(gl);
	}
	
	public void renderLines(GL gl) {
		if( closed )
			gl.glBegin(GL.GL_LINE_LOOP);
		else
			gl.glBegin(GL.GL_LINE_STRIP);
		renderPoints(gl);
		gl.glEnd();
	}
	
	
	public void writeText(Writer file) throws IOException {
		file.write(name.replace(' ', '_') + '\n');
		file.write(getVertexCount() + "\n");
		for(EditVertex v: getVertices())
			file.write(v.saveId + " ");
		file.write("\n");
		
		if( type != null )
			file.write(type.getId()+"\n");
		else
			file.write(-1+"\n");
		
		file.write(restypes.size()+"\n");
		for(ResourceType r:restypes)
			file.write(r.getId() + " ");
		
		file.write(adjs.size()+"\n");
		for(EditPoly p:adjs)
			file.write(p.saveId + " ");
		file.write("\n");
	}
	
	public void readText(Scanner file, EditMap map) {
		name = file.next().replace('_', ' ');
		int npv = file.nextInt();
		verts.clear();
		for(int j=0;j<npv;++j)
			addVertex( map.getVertex(file.nextInt()) );
		addToVertices();
		int typeid = file.nextInt();
		if(typeid!=-1)
			type = map.getRegionType( typeid );
		else
			type = null;
		int npr = file.nextInt();
		for(int i=0;i<npr;++i)
			restypes.add(map.getResourceType(file.nextInt()));
		int npa = file.nextInt();
		for(int i=0;i<npa;++i)
			adjs.add( map.getPolygons().get(file.nextInt()) );
		close();
	}
	
	public void setType(RegionType newType) {
		type = newType;
	}
	
	
	public RegionType getType() { return type; }
	
	public ArrayList<ResourceType>	getResources() { return restypes; }
	public ArrayList<EditPoly>		getAdjacent() { return adjs; }
	public void addAdjacent(EditPoly p) {
		adjs.add(p);
		p.adjs.add(this);
	}
	
	public void removeAdjacent(EditPoly p) {
		adjs.remove(p);
		p.adjs.remove(this);
	}
	public boolean isAdjacentTo(EditPoly p) {
		return adjs.contains(p);
	}
	
	public Vector2 getCenter() { return center; }
	
	
	public String getName() { return name; }
	public void setName(String newName) { if(newName==null) throw new NullPointerException(); name=newName; }
	public void addResource( ResourceType rt ) { assert(rt!=null); restypes.add(rt); }
	public void removeResource( ResourceType rt ) { assert(rt!=null); restypes.remove(rt); }
	
	private void updateCenter() {
		if( verts.size()>0 ) {
			center.set(vertsum);
			center.mul(1.0/verts.size());
		}
	}
	
	private String name = "<unnamed>";
	private ArrayList<EditVertex>	verts;
	private ArrayList<ResourceType> restypes = new ArrayList<ResourceType>();
	private ArrayList<EditPoly>		adjs = new ArrayList<EditPoly>();
	private RegionType type = null;
	private boolean closed=false;
	private Vector2 vertsum = new Vector2(0.0,0.0), center = new Vector2(0.0,0.0);
	
	public int saveId;
}
